{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. 单层感知机"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义式：\n",
    "\n",
    "$$\n",
    "    y = w_1x_1 + w_2x_2 + ... + w_nx_n + b\n",
    "$$\n",
    "\n",
    "如果只考虑两个因素，即输入数据维度是2，感知机函数为$y = w_1x_1 + w_2x_2 + b$，在三维坐标系里是一个平面$w_1x_1 + w_2x_2 - y + b = 0$，只能将三维空间划分为两个空间，所以输出的结果只有两类。同样的，对于更高维度的空间，感知机函数所能做的也仅仅时将其划分为两个空间，感知机函数所对应的平面\n",
    "$w_1x_1 + w_2x_2 + ... + w_nx_n - y + b = 0$称为**超平面**。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "感知机的缺陷：**无法解决异或问题**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [实验一] 实现单隐藏层为256的多层感知机"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch: 1, loss: 0.6910132884979248, accuracy: 0.73671875\n",
      "epoch: 2, loss: 0.5549683570861816, accuracy: 0.80517578125\n",
      "epoch: 3, loss: 0.5547346591949462, accuracy: 0.8021484375\n",
      "epoch: 4, loss: 0.4781937122344971, accuracy: 0.8296875\n",
      "epoch: 5, loss: 0.46979646682739257, accuracy: 0.833984375\n",
      "epoch: 6, loss: 0.4715888500213623, accuracy: 0.83291015625\n",
      "epoch: 7, loss: 0.44906301498413087, accuracy: 0.838671875\n",
      "epoch: 8, loss: 0.5003121852874756, accuracy: 0.81904296875\n",
      "epoch: 9, loss: 0.4304527759552002, accuracy: 0.84521484375\n",
      "epoch: 10, loss: 0.45417037010192873, accuracy: 0.83759765625\n",
      "epoch: 11, loss: 0.4164729118347168, accuracy: 0.853125\n",
      "epoch: 12, loss: 0.4026285171508789, accuracy: 0.85419921875\n",
      "epoch: 13, loss: 0.50434889793396, accuracy: 0.81484375\n",
      "epoch: 14, loss: 0.4217700481414795, accuracy: 0.84365234375\n",
      "epoch: 15, loss: 0.415385103225708, accuracy: 0.84541015625\n",
      "epoch: 16, loss: 0.38382141590118407, accuracy: 0.8625\n",
      "epoch: 17, loss: 0.39549458026885986, accuracy: 0.85888671875\n",
      "epoch: 18, loss: 0.3695842266082764, accuracy: 0.8669921875\n",
      "epoch: 19, loss: 0.3911224365234375, accuracy: 0.85615234375\n",
      "epoch: 20, loss: 0.3788726568222046, accuracy: 0.86494140625\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x23989607df0>]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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pdNqQYH8W+/QwbHjbNgg/2bCw6X2MTzcueUkcidb799BbiwTeYnAQOfUHlStKh1Ie/aUqucHH6z4PXfdBXTubAoyyluqVTPdgLdulfNUxF2h9+uvSyBSs6bMyOqKQGHSJKlx2blTakfuusv55yDbff21BCItW8rwbUfdcYdk5/3jDxl5NXas04pI5LEYjJBb2Dpa54UXHAuEevSQPiFnzpQfcIwaJTU+48cDQS761//zzzJqBpBhmg0buuY8UVHA008Db78teUf69mXtiJZWrZLHBx6o3HUICJBhvv/4h2RkffppXlfyfRzaS25hDBas/aeq00nflB49HDt+YCDw7rumY5U+tk4nSaUKCoDnnpOOn3v3Onau8ly9CgwfLk1d999ve9IrR73wgky29tNPHA6qpT//BP77X1l3xjUfMQKoXl06sTKfDPkDBiPkFhUFC4B0kq3MSJfBg2VETumaiJgY2f7rr8DixZLLYfdu4JZbJMX61auOn7O0l18GDh4EoqOBDz5w/S/aevVM1fjMyqqdzz+Xzto33wy0alX540VEAI8+Kuvz5lX+eESejh1Yya0qM1rHVhV1wM3KkirwNWvkefPmwKJFle8ns3Ur0KuXBATffgv061e549nq3DkZWXPlCvDNNzIag9yrVy8ZqfXGG1Jb5QwZGRLY6HTA4cPADTc457hE7sTRNOSxnDVap7K++kra442jcB5/HJg9W2pO7JWbC7RrB5w4IcdZtMipRa3QpEnAm28CnTpJk41WfQw85dq609mzUvumlOQWadLEecfu00eaf559FnjrLecdl8hdbL1/s5mG3M44WmfYMHnU6mY1cKDkAhkzRp7/619A69aOpY5PTJRApEkTYM4cpxbTJs8/L6OLdu+WWhkteGIqfndYs0YCkfh45wYigGk238WLJf8Oka9iMEJ+LTJS+nZ8/70MyczKkmnfBw+2LW8JIE0jixdLbcTy5drkhahTx3Tj0mLOGmP23tIzP585I9t9OSAxzkXjivw1d90lzTOXLgH//rfzj0/kKRiMEEGaE/buBV55RYb8fvGF1JJ89FH5M6heuCBZYwGpHfm//3NLcS169lkZgZGeLjkv3EWvl35AlgIg47YJEzxj9mRnO3YM+PFHGY57333OP35goKmD8rx57KBMvovBCNH/hIVJfpD0dKBLF+kH8uST0jnxjz9M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1xWA+uKLL4qfGwwGFR0drWbPnl287dKlSyo0NFStWrXK6nG6dOmixo4dW/xcr9erBg0aqFmzZrmk3I4o/Vkt2bVrlwKgTpw4YXUfe78LWrH0eUeMGKEGDhxo13F85doOHDhQ9erVq9x9vOXalr7XXLp0SQUHB6s1a9YU73Pw4EEFQKWlpVk8hqPfdXuwZkQjOTk5AIBatWqVu9/ly5fRuHFjxMbGYuDAgThw4IA7ildphw4dQoMGDXDDDTfgoYcewsmTJ63um5aWhoSEBLNtffr0QVpamquL6XRFRUVYsWIFHnvssXIndfTW61rSsWPHkJWVZXbtIiMjERcXZ/XaFRUVYffu3WbvCQgIQEJCgtdd75ycHOh0OtSoUaPc/ez5LniarVu3ol69emjZsiXGjBmDP//80+q+vnJts7OzsW7dOowaNarCfb3h2pa+1+zevRvXrl0zu06tWrVCo0aNrF4nR77r9mIwogGDwYAJEyagW7duuOmmm6zu17JlSyxZsgRfffUVVqxYAYPBgK5du+L06dNuLK394uLisGzZMqxfvx4LFizAsWPH0KNHD+Tl5VncPysrC1FRUWbboqKikJWV5Y7iOtWXX36JS5cu4dFHH7W6j7de19KM18eea3fhwgXo9Xqvv94FBQWYNGkShg0bVu7EYvZ+FzxJ37598fHHHyMlJQVvvPEGtm3bhrvuugt6vd7i/r5ybZcvX47w8PAKmy284dpautdkZWUhJCSkTBBd3nVy5LtuL6+YtdfXjB07Fvv376+wfTE+Ph7x8fHFz7t27YrWrVvjww8/xMyZM11dTIfdddddxevt2rVDXFwcGjdujM8++8ymXxvebPHixbjrrrvQoEEDq/t463Ulce3aNdx///1QSmHBggXl7uvN34UHHnigeL1t27Zo164dmjVrhq1bt6J3794alsy1lixZgoceeqjCTuXecG1tvdd4AtaMuNm4cePw7bffYsuWLYiJibHrvcHBwejQoQMOHz7sotK5Ro0aNdCiRQur5Y6Oji7Tkzs7OxvR0dHuKJ7TnDhxAps2bcLjjz9u1/u89boar489165OnToIDAz02uttDEROnDiBjRs32j3dekXfBU92ww03oE6dOlbL7u3XFgBSU1ORkZFh93cY8Lxra+1eEx0djaKiIly6dMls//KukyPfdXsxGHETpRTGjRuHL774Aps3b0bTpk3tPoZer8e+fftQv359F5TQdS5fvowjR45YLXd8fDxSUlLMtm3cuNGs9sAbLF26FPXq1UO/fv3sep+3XtemTZsiOjra7Nrl5uZi586dVq9dSEgIOnXqZPYeg8GAlJQUj7/exkDk0KFD2LRpE2rXrm33MSr6Lniy06dP488//7Radm++tkaLFy9Gp06d0L59e7vf6ynXtqJ7TadOnRAcHGx2nTIyMnDy5Emr18mR77ojBSc3GDNmjIqMjFRbt25VmZmZxcuVK1eK93nkkUfUiy++WPx8+vTpasOGDerIkSNq9+7d6oEHHlBhYWHqwIEDWnwEmz377LNq69at6tixY2rHjh0qISFB1alTR507d04pVfZz7tixQwUFBam33npLHTx4UCUlJang4GC1b98+rT6C3fR6vWrUqJGaNGlSmde8+brm5eWpPXv2qD179igAas6cOWrPnj3FI0j++c9/qho1aqivvvpK/frrr2rgwIGqadOm6urVq8XH6NWrl5o3b17x808//VSFhoaqZcuWqd9++0098cQTqkaNGiorK8vtn6+k8j5rUVGRGjBggIqJiVF79+41+w4XFhYWH6P0Z63ou6Cl8j5vXl6eeu6551RaWpo6duyY2rRpk+rYsaP629/+pgoKCoqP4QvX1ignJ0dVrVpVLViwwOIxvOXa2nKveeqpp1SjRo3U5s2b1c8//6zi4+NVfHy82XFatmypkpOTi5/b8l2vDAYjbgLA4rJ06dLifW677TY1YsSI4ucTJkxQjRo1UiEhISoqKkrdfffdKj093f2Ft9PQoUNV/fr1VUhIiGrYsKEaOnSoOnz4cPHrpT+nUkp99tlnqkWLFiokJETdeOONat26dW4udeVs2LBBAVAZGRllXvPm67plyxaL/26Nn8dgMKgpU6aoqKgoFRoaqnr37l3mb9C4cWOVlJRktm3evHnFf4MuXbqoH3/80U2fyLryPuuxY8esfoe3bNlSfIzSn7Wi74KWyvu8V65cUXfeeaeqW7euCg4OVo0bN1ajR48uE1T4wrU1+vDDD1WVKlXUpUuXLB7DW66tLfeaq1evqqefflrVrFlTVa1aVd1zzz0qMzOzzHFKvseW73pl6P53UiIiIiJNsM8IERERaYrBCBEREWmKwQgRERFpisEIERERaYrBCBEREWmKwQgRERFpisEIERERaYrBCBEREWmKwQgRERFpisEIERERaYrBCBEREWmKwQgRERFp6v8BKVM+yvlNoDUAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "from d2l import torch as d2l\n",
    "import matplotlib.pyplot as plt\n",
    "from MyModule.Utils import accuracy_Fmnist\n",
    "\n",
    "batch_size = 256\n",
    "train_dataLoader, test_dataLoader = d2l.load_data_fashion_mnist(batch_size)\n",
    "\n",
    "nums_input = 784\n",
    "nums_hidden = 256\n",
    "nums_output = 10\n",
    "\n",
    "w1 = nn.Parameter(      # 将torch的tensor包装成参数，以便优化器能够识别并更新这些参数\n",
    "    torch.randn(size=(nums_input, nums_hidden)) * 0.01\n",
    ")\n",
    "\n",
    "b1 = nn.Parameter(\n",
    "   torch.zeros(nums_hidden)\n",
    ")\n",
    "\n",
    "w2 = nn.Parameter(\n",
    "    torch.randn(size=(nums_hidden, nums_output)) * 0.01\n",
    ")\n",
    "\n",
    "b2 = nn.Parameter(\n",
    "    torch.zeros(nums_output)\n",
    ")\n",
    "\n",
    "# 前向传播\n",
    "def forward(x):\n",
    "    x = x.reshape(-1, nums_input)\n",
    "    x = torch.relu(x@w1 + b1)\n",
    "    x = x@w2 + b2\n",
    "    return x\n",
    "\n",
    "# 损失函数\n",
    "loss = nn.CrossEntropyLoss()\n",
    "\n",
    "# 优化器\n",
    "optimzer = torch.optim.SGD([w1,b1,w2,b2], lr = 0.1)\n",
    "\n",
    "# 训练\n",
    "losses = []\n",
    "accuracies = []\n",
    "num_epoch = []\n",
    "epochs = 20\n",
    "for epoch in range(epochs):\n",
    "    train_iter = iter(train_dataLoader)\n",
    "    for x,y in train_iter:\n",
    "        l = loss(forward(x), y)\n",
    "        optimzer.zero_grad()\n",
    "        l.backward()\n",
    "        optimzer.step()\n",
    "\n",
    "    # 求测试集loss\n",
    "    test_iter = iter(test_dataLoader)\n",
    "    total_loss = 0\n",
    "    total_accuracy = 0\n",
    "    for x,y in test_iter:\n",
    "        output = forward(x)\n",
    "        l = loss(output, y)\n",
    "        total_loss += l\n",
    "        total_accuracy += accuracy_Fmnist(output, y)\n",
    "\n",
    "    epoch_loss = total_loss.item() / len(test_iter)\n",
    "    epoch_accuracy = total_accuracy.item() / len(test_iter)\n",
    "    print(f'epoch: {epoch + 1}, loss: {epoch_loss}, accuracy: {epoch_accuracy}')\n",
    "    num_epoch.append(epoch+1)\n",
    "    losses.append(epoch_loss)\n",
    "    accuracies.append(epoch_accuracy)\n",
    "\n",
    "plt.figure()\n",
    "plt.plot(num_epoch, losses, color='blue', label='Loss', marker='o')\n",
    "plt.plot(num_epoch, accuracies, color='red', label='Accuracy', marker='x')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "torch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
